//! 错误类型模块
//!
//! 定义 log4r 的错误类型，提供统一的错误处理机制。
//!
//! ## 主要类型
//!
//! - [`Log4rError`] - 错误枚举，包含配置错误、IO 错误等
//! - [`Result<T>`] - log4r 专用 Result 类型别名
//!
//! ## 示例
//!
//! ```rust
//! use log4r::Log4rError;
//!
//! // 使用便捷构造函数创建错误
//! let config_err = Log4rError::config("无效的配置格式");
//! let appender_err = Log4rError::appender("FileAppender", "无法打开文件");
//!
//! // 错误显示
//! println!("{}", config_err);  // 输出: 配置错误: 无效的配置格式
//! ```

use thiserror::Error;

/// log4r 错误类型
///
/// 统一的错误类型，用于表示 log4r 中可能发生的各种错误。
///
/// # 变体
///
/// - `ConfigError` - 配置解析错误
/// - `IoError` - IO 操作错误
/// - `AppenderError` - Appender 相关错误
/// - `AlreadyInitialized` - 日志系统重复初始化错误
///
/// # 示例
///
/// ```rust
/// use log4r::Log4rError;
///
/// // 创建配置错误
/// let err = Log4rError::config("配置文件格式错误");
/// assert!(err.to_string().contains("配置错误"));
///
/// // 创建 Appender 错误
/// let err = Log4rError::appender("console", "输出失败");
/// assert!(err.to_string().contains("Appender"));
/// ```
#[derive(Debug, Error)]
pub enum Log4rError {
    /// 配置错误
    ///
    /// 当配置文件解析失败或配置值无效时返回此错误。
    #[error("配置错误: {0}")]
    ConfigError(String),

    /// IO 错误
    ///
    /// 当文件读写或其他 IO 操作失败时返回此错误。
    /// 支持从 `std::io::Error` 自动转换。
    #[error("IO 错误: {0}")]
    IoError(#[from] std::io::Error),

    /// Appender 错误
    ///
    /// 当 Appender 操作失败时返回此错误。
    #[error("Appender '{name}' 错误: {cause}")]
    AppenderError {
        /// Appender 名称
        name: String,
        /// 错误原因
        cause: String,
    },

    /// 重复初始化错误
    ///
    /// 当日志系统已经初始化后再次调用初始化函数时返回此错误。
    #[error("日志系统已初始化")]
    AlreadyInitialized,

    /// 未初始化错误
    ///
    /// 当日志系统未初始化时调用需要初始化的函数时返回此错误。
    #[error("日志系统未初始化")]
    NotInitialized,

    /// 关闭超时错误
    ///
    /// 当 shutdown 操作超过指定时间未完成时返回此错误。
    #[error("关闭超时: {0} 秒后仍未完成")]
    ShutdownTimeout(u64),

    /// 通道错误
    ///
    /// 当消息通道操作失败时返回此错误（如发送失败、接收端断开）。
    #[error("通道错误: {0}")]
    ChannelError(String),
}

impl Log4rError {
    /// 创建配置错误
    ///
    /// # 参数
    ///
    /// * `msg` - 错误消息
    ///
    /// # 示例
    ///
    /// ```rust
    /// use log4r::Log4rError;
    ///
    /// let err = Log4rError::config("无效的日志级别");
    /// assert!(err.to_string().contains("配置错误"));
    /// ```
    pub fn config(msg: impl Into<String>) -> Self {
        Self::ConfigError(msg.into())
    }

    /// 创建 Appender 错误
    ///
    /// # 参数
    ///
    /// * `name` - Appender 名称
    /// * `cause` - 错误原因
    ///
    /// # 示例
    ///
    /// ```rust
    /// use log4r::Log4rError;
    ///
    /// let err = Log4rError::appender("FileAppender", "无法创建日志文件");
    /// assert!(err.to_string().contains("FileAppender"));
    /// ```
    pub fn appender(name: impl Into<String>, cause: impl Into<String>) -> Self {
        Self::AppenderError {
            name: name.into(),
            cause: cause.into(),
        }
    }
}

/// log4r 专用 Result 类型别名
pub type Result<T> = std::result::Result<T, Log4rError>;

#[cfg(test)]
mod tests {
    use super::*;

    /// [P0] 测试 AlreadyInitialized 变体创建和显示 (AC-2.3.1, AC-2.3.3)
    #[test]
    fn test_already_initialized() {
        // GIVEN: AlreadyInitialized 错误
        // WHEN: 创建错误
        let error = Log4rError::AlreadyInitialized;

        // THEN: 应正确显示中文错误信息
        let display = error.to_string();
        assert!(display.contains("已初始化"));
        assert_eq!(display, "日志系统已初始化");
    }

    /// [P0] 测试便捷构造函数 config() (AC-2.3.1)
    #[test]
    fn test_config_convenience() {
        // GIVEN: 错误消息
        let msg = "无效的配置";

        // WHEN: 使用便捷构造函数
        let error = Log4rError::config(msg);

        // THEN: 应创建 ConfigError 变体
        let display = error.to_string();
        assert!(display.contains("配置错误"));
        assert!(display.contains(msg));
    }

    /// [P0] 测试便捷构造函数 appender() (AC-2.3.1)
    #[test]
    fn test_appender_convenience() {
        // GIVEN: Appender 信息
        let name = "TestAppender";
        let cause = "测试错误";

        // WHEN: 使用便捷构造函数
        let error = Log4rError::appender(name, cause);

        // THEN: 应创建 AppenderError 变体
        let display = error.to_string();
        assert!(display.contains(name));
        assert!(display.contains(cause));
    }

    /// [P1] 测试便捷构造函数接受 &str 和 String (AC-2.3.1)
    #[test]
    fn test_convenience_accepts_various_types() {
        // GIVEN: 不同类型的输入
        // WHEN: 使用 &str
        let err1 = Log4rError::config("静态字符串");
        // WHEN: 使用 String
        let err2 = Log4rError::config(String::from("动态字符串"));
        // WHEN: 使用 &String
        let s = String::from("引用字符串");
        let err3 = Log4rError::config(&s);

        // THEN: 都应成功创建
        assert!(err1.to_string().contains("静态字符串"));
        assert!(err2.to_string().contains("动态字符串"));
        assert!(err3.to_string().contains("引用字符串"));
    }

    /// [P0] 测试 NotInitialized 变体创建和显示 (AC-7.4)
    #[test]
    fn test_not_initialized() {
        // GIVEN: NotInitialized 错误
        // WHEN: 创建错误
        let error = Log4rError::NotInitialized;

        // THEN: 应正确显示中文错误信息
        let display = error.to_string();
        assert!(display.contains("未初始化"));
    }

    /// [P0] 测试 ShutdownTimeout 变体创建和显示 (AC-7.4)
    #[test]
    fn test_shutdown_timeout() {
        // GIVEN: ShutdownTimeout 错误
        // WHEN: 创建错误
        let error = Log4rError::ShutdownTimeout(5);

        // THEN: 应正确显示超时时间
        let display = error.to_string();
        assert!(display.contains("5"));
        assert!(display.contains("超时"));
    }
}
